#include "common_api.h"
#include "luat_rtos.h"
#include "luat_debug.h"
#include "luat_uart.h"
#include "luat_gpio.h"
#include "pikaScript.h"
#include "pika_config.h"
#include "luat_fs.h"
#include "luat_mem.h"
#include "luat_spi.h"
#include "iconv.h"
#define USER_UART_ID LUAT_VUART_ID_0
#define RX_BUF_LEN 1024

typedef struct
{
    char buf[RX_BUF_LEN];
    int pos;
    int len;
}rx_buf;
static volatile rx_buf s_rx_buf = {.pos = 0, .len = 0};
static luat_rtos_task_handle pika_main_handle;
void task_gpio_input_run(void);

luat_rtos_task_handle task1_handle;
luat_rtos_task_handle task2_handle;


static void hw_demoA_init(void)
{
	LUAT_DEBUG_PRINT("this hw demo1");
}

static void hw_demoB_init(void)
{
	LUAT_DEBUG_PRINT("this hw demo2");
}

static void dr_demoC_init(void)
{
	LUAT_DEBUG_PRINT("this dr demo1");
}

static void dr_demoD_init(void)
{
	LUAT_DEBUG_PRINT("this dr demo2");
}

static void task1(void *param)
{
	while(1)
	{
		luat_rtos_task_sleep(1000);
		LUAT_DEBUG_PRINT("task1 loop");
	}
}

static void task2(void *param)
{
	while(1)
	{
		luat_rtos_task_sleep(1000);
		LUAT_DEBUG_PRINT("task2 loop");
		// 去掉下面的注释, 可以关闭日志打印
		// luat_debug_print_onoff(0);
	}
}

static void task_demoE_init(void)
{
	luat_rtos_task_create(&task1_handle, 2*1024, 50, "task_gpio_input_run", task_gpio_input_run, NULL, 0);
}
static void task_demoG_init(void)
{
	luat_rtos_task_create(&task2_handle, 2*1024, 50, "task_gpio_input_run", task_gpio_input_run, NULL, 0);
}
static void task_demoF_init(void)
{
	luat_rtos_task_create(&task2_handle, 2*1024, 50, "task2", task2, NULL, 0);
}



void luat_usb_recv_cb(int uart_id, uint32_t data_len){
    s_rx_buf.len += luat_uart_read(uart_id, (void*)&s_rx_buf.buf[s_rx_buf.len], (data_len > (1024 - s_rx_buf.len)?(1024 - s_rx_buf.len):data_len));

	// char* data_buff = malloc(data_len);
    // luat_uart_read(uart_id, data_buff, data_len);
    // LUAT_DEBUG_PRINT("luat_uart_cb uart_id:%d data:%.*s data_len:%d",uart_id, data_len, data_buff,data_len);
    // free(data_buff);

}

int pika_platform_putchar(char ch) {
    return luat_uart_write(USER_UART_ID, &ch, 1);
}

char pika_platform_getchar(void) {
	while (s_rx_buf.pos >= s_rx_buf.len)
	{
		s_rx_buf.pos = 0;
		s_rx_buf.len = 0;
		luat_rtos_task_sleep(1);
	}

	return s_rx_buf.buf[s_rx_buf.pos++];
}

int gpio_irq(int pin, void* args)
{
	LUAT_DEBUG_PRINT("pin:%d, level:%d,", pin, luat_gpio_get(pin));
}



void task_gpio_input_run(void)
{

	luat_gpio_cfg_t gpio_cfg;

	luat_gpio_set_default_cfg(&gpio_cfg);
	gpio_cfg.pin = HAL_GPIO_22;
	gpio_cfg.mode = LUAT_GPIO_IRQ;
	gpio_cfg.irq_type = LUAT_GPIO_RISING_IRQ; 
	gpio_cfg.pull = LUAT_GPIO_PULLDOWN;
	gpio_cfg.irq_cb = gpio_irq;	
	luat_gpio_open(&gpio_cfg);

	//输出到LED
	luat_gpio_set_default_cfg(&gpio_cfg);
	gpio_cfg.pin = HAL_GPIO_7;
	gpio_cfg.mode = LUAT_GPIO_OUTPUT;
	luat_gpio_open(&gpio_cfg);
	luat_gpio_set(HAL_GPIO_7, 1);
	while (1)
	{
		// LUAT_DEBUG_PRINT("#1 %lf", 1.5);
		// pika_platform_printf("#1 %lf\n", 1.5);
		// LUAT_DEBUG_PRINT("#2 %lf", 6.7);
		// pika_platform_printf("#2 %lf\n", 6123.7);
		luat_rtos_task_sleep(1000);
	}
	
}


static int print_fs_info()
{
    luat_fs_info_t fs_info = {0};

    luat_fs_info("/", &fs_info);
    // 打印文件系统空间信息
    LUAT_DEBUG_PRINT("fs_info %s %d %d %d %d", 
        fs_info.filesystem, 
        fs_info.type, 
        fs_info.total_block, 
        fs_info.block_used, 
        fs_info.block_size);
}

// 演示文件夹操作
void exmaple_fs_lfs_dir(void)
{
    int ret=-1;
    ret=luat_fs_mkdir("luatos");
    LUAT_DEBUG_PRINT("mkdir result%d",ret);
    if (0==ret)
    {
       LUAT_DEBUG_PRINT("mkdir succeed");
    }
    FILE* fp = NULL;
    uint8_t *buff = NULL;
    const char* filepath = "luatos/luatos_test.txt";
    fp = luat_fs_fopen(filepath, "wb+");
    if (!fp)
    {
       LUAT_DEBUG_PRINT("file open failed %s", filepath);
       return;
    }
    luat_fs_fclose(fp);
}

static int recur_fs(const char* dir_path)
{
    luat_fs_dirent_t *fs_dirent = LUAT_MEM_MALLOC(sizeof(luat_fs_dirent_t)*100);
    memset(fs_dirent, 0, sizeof(luat_fs_dirent_t)*100);

    int lsdir_cnt = luat_fs_lsdir(dir_path, fs_dirent, 0, 100);

    if (lsdir_cnt > 0)
    {
        char path[255] = {0};

        LUAT_DEBUG_PRINT("dir_path=%s, lsdir_cnt=%d", dir_path, lsdir_cnt);

        for (size_t i = 0; i < lsdir_cnt; i++)
        {
            memset(path, 0, sizeof(path));            

            switch ((fs_dirent+i)->d_type)
            {
            // 文件类型
            case 0:   
                snprintf(path, sizeof(path)-1, "%s%s", dir_path, (fs_dirent+i)->d_name);             
                LUAT_DEBUG_PRINT("\tfile=%s, size=%d", path, luat_fs_fsize(path));
                break;
            case 1:
                snprintf(path, sizeof(path)-1, "%s/%s", dir_path, (fs_dirent+i)->d_name);
                recur_fs(path);
                break;

            default:
                break;
            }
        }        
    }

    LUAT_MEM_FREE(fs_dirent);
    fs_dirent = NULL;
    
    return lsdir_cnt;
}


static void pika_main(void *param)
{
	LUAT_DEBUG_PRINT("pika start");
    luat_uart_t uart = {
        .id = USER_UART_ID,
    };

    luat_uart_setup(&uart);

    luat_uart_ctrl(LUAT_VUART_ID_0, LUAT_UART_SET_RECV_CALLBACK, luat_usb_recv_cb);

	//--------- 初始化文件系统
	luat_fs_init(); // 必须先初始化    

    // luat_spi_setup(&sfud_spi_flash);
	// int re = -1;
	// re = sfud_init();
	// LUAT_DEBUG_PRINT("re: %d\n", re);
    // if (re!=0){
    //     LUAT_DEBUG_PRINT("sfud_init error is %d\n", re);
    // }
    
    // print_fs_info(); // 打印文件系统信息 
	// exmaple_fs_lfs_dir();
	// recur_fs("/");
    // recur_fs("luatos");

	PikaObj * pikaMain = pikaScriptInit();
	LUAT_DEBUG_PRINT("pika exit");
	
	while(1){
		luat_rtos_task_sleep(15000);
	}
	// while(1)
	// {
	// 	luat_rtos_task_sleep(1000);
	// 	LUAT_DEBUG_PRINT("task1 loop");
	// }
	// while(1)
	// {
	// 	pikaScriptShell(pikaMain);
	// }
}


void pika_main_init(void)
{
	// luat_rtos_task_create(&task1_handle, 2*1024, 50, "task1", task1, NULL, 0);
	luat_rtos_task_create(&pika_main_handle, 16 * 1024, 50, "pika_main", pika_main, NULL, 32);
}

INIT_TASK_EXPORT(pika_main_init, "1");
//启动task_demoE_init，启动位置任务1级
// INIT_TASK_EXPORT(task_demoE_init, "1");
// INIT_TASK_EXPORT(task_demoG_init, "1");
